package com.utilities.fastaUtilities;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
import java.util.TreeSet;

import com.utilities.IO.FileUtilities;
import com.utilities.IO.fileWriters.PrepareAllFeaturesFiles;
import com.utilities.parsers.gbkFileParser.ParseEvents;
import com.utilities.parsers.gbkFileParser.ParseGBKFileParser;
import com.utilities.parsers.gbkFileParser.ParseListener;

public class OtherUtilities 
{
	public static HashMap<String, String> getContigStats(String contigsFile) throws Exception 
	{
		HashMap<String, String> hashMap = new HashMap<String, String>();
		BufferedReader bufferedReader = new BufferedReader(new FileReader(contigsFile));
        String str = bufferedReader.readLine();
        String contigBeingRead = null;
        int contigLength = 0;
        while(str != null)
        {
        	if (str.startsWith(">"))
        	{
        		contigBeingRead = str.split(" ")[0].substring(1);
        		if (contigLength != 0)
        		{
        			hashMap.put(contigBeingRead, String.valueOf(contigLength));
        		}
        		contigLength = 0;
        	}
        	else
        	{
        		contigLength = contigLength + str.trim().length();
        	}
        	str = bufferedReader.readLine();
        }
        bufferedReader.close();
		return hashMap;
	}
	public static Set<String> fastaHeader(String geneFile, String[] filterStrings) throws Exception
	{
		TreeSet<String> geneSet = new TreeSet<String>();
		RandomAccessFile rand = new RandomAccessFile(geneFile, "r");
		String readLine = rand.readLine();
		while(readLine != null)
		{
			if (readLine.startsWith(">")) 
			{
				boolean consider = true;
				if (filterStrings != null)
				{
					for(String filterString : filterStrings)
					{
						if (readLine.contains(filterString))
						{
							consider = false;
							break;
						}
					}
				}
				if (consider)
				{
					readLine = readLine.substring(1);
					geneSet.add(readLine);
				}
			}
			readLine = rand.readLine();
		}
		rand.close();
//		System.out.println("Genes read...");
		return geneSet;
	}
	
	public static ArrayList<String> getSequenceNames(String fileName)
	{
		ArrayList<String> lst = new ArrayList<String>();
		try
		{
			BufferedReader bufferedReader = new BufferedReader(new FileReader(fileName));
			String readLine = bufferedReader.readLine();
			while(readLine != null)
			{
				if (readLine.startsWith(">"))
				{
					String contigName = readLine.split(" ")[0].substring(1).trim();
					lst.add(contigName);
				}
				readLine = bufferedReader.readLine();
			}
			bufferedReader.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return lst;
	}
	
	public static int findGCContent(String str)
	{
		int result = 0 ;
		for (int i = 0 ; i < str.length(); i++)
		{
			char ch = str.charAt(i);
			if (ch == 'G' || ch == 'g' || ch == 'c' || ch == 'C')
			{
				result++;
			}
		}
		return result;
	}
	
	public static void reverseComplement(String[] args) throws Exception
	{
		if (args == null )
		{
			args = new String[4];
			// input file
			args[0] = "C:/Users/bansalp/Desktop/DeNovo/singleEnd/contigs/NODE_404_length_6812_cov_28.995890.txt";
			args[1] = "C:/Users/bansalp/Desktop/DeNovo/singleEnd/Reverse404.txt";
		}
		
		FileWriter fw = new FileWriter(new File(args[1]));
		File f = new File(args[0]);
        FileReader fr = new FileReader(f);
        BufferedReader bufferedReader = new BufferedReader(fr);
        String str = bufferedReader.readLine();
        fw.write(str + "\n");
        str = bufferedReader.readLine();
        StringBuffer buffer = new StringBuffer();
        while(str != null)
        {
        	buffer.append(str.trim());
        	str = bufferedReader.readLine();
        }
        bufferedReader.close();
        buffer = buffer.reverse();
        for (int i = 0 ; i < buffer.length();i++)
        {
        	char ch = buffer.charAt(i);
        	switch(ch)
    		{
    		case 'A' : ch = 'T';
    					break;
    		case 'a' : ch = 't';
    					break;
    		case 'C' : ch = 'G';
    					break;
    		case 'c' : ch = 'g';
    				    break;
    		case 'T' : ch = 'A';
    					break;
    		case 't' : ch = 'a';
    					break;
    		case 'G' : ch = 'C';
    					break;
    		case 'g' : ch = 'c';
    					break;
    		}
        	fw.write(ch);
        	if ( (i + 1)% 60 == 0)
        	{
        		fw.write("\n");
        	}
        }
        fw.flush();
        fw.close();
//        fr = new FileReader(f);
        
        
//        RandomAccessFile accessFile = new RandomAccessFile(f, "r");
//        StringBuffer buffer = new StringBuffer();
//        for (long length = f.length() - 1; length > str.length() ; length--)
//        {
//        	accessFile.seek(length);
//        	char ch = (char)accessFile.readByte();
//        	if (ch != '\n' && ch != '\r')
//        	{
//        		switch(ch)
//        		{
//        		case 'A' : ch = 'T';
//        					break;
//        		case 'a' : ch = 't';
//        					break;
//        		case 'C' : ch = 'G';
//        					break;
//        		case 'c' : ch = 'g';
//        				    break;
//        		case 'T' : ch = 'A';
//        					break;
//        		case 't' : ch = 'a';
//        					break;
//        		case 'G' : ch = 'C';
//        					break;
//        		case 'g' : ch = 'c';
//        					break;
//        		}
//        		buffer.append(ch);
//            	if (buffer.length() == 60)
//            	{
//            		fw.write(buffer.toString() + "\n");
//            		buffer = new StringBuffer();
//            	}
//        	}
//        }
//        fw.flush();
//        fw.close();
	}
	
	/**
	 * args[0] : paths of the file containing ordered contigs names
	 * args[1] : path of the contigs file
	 * args[2] : path of the rearrangend contigs file
	 * @param args
	 */
	public void reArrangeContigs(String[] args)
	{
		try
		{
			ArrayList<String> list = new ArrayList<String>();
			BufferedReader bufferedReader = new BufferedReader(new FileReader(args[0]));
			String readLine = bufferedReader.readLine();
			while(readLine != null)
			{
				list.add(readLine.trim());
				readLine = bufferedReader.readLine();
			} 
			bufferedReader.close();
			
			FileWriter fw = new FileWriter(args[2]);
			for (String contig : list)
			{
				bufferedReader = new BufferedReader(new FileReader(args[1]));
				readLine = bufferedReader.readLine();
				boolean startReading = false;
				while(readLine != null)
				{
					if (readLine.startsWith(">"))
					{
						if (startReading)
						{
							break;
						}
						else if (readLine.contains(contig))
						{
							fw.write(readLine.trim() + "\n");
//							System.out.println(contig);
							startReading = true;
						}
					}
					else if (startReading)
					{
						fw.write(readLine.trim() + "\n");
					}
					readLine = bufferedReader.readLine();
				} 
				bufferedReader.close();
			}

			bufferedReader = new BufferedReader(new FileReader(args[1]));
			readLine = bufferedReader.readLine();
			boolean skip = false;
			while(readLine != null)
			{
				if (readLine.startsWith(">"))
				{
					skip = false;
					for (String contig : list)
					{
						if (readLine.contains(contig))
						{
							skip = true;
							break;
						}	
					}
				}
				if (!skip)
				{
					fw.write(readLine.trim()+"\n");
				}
				readLine = bufferedReader.readLine();
			}

			fw.flush();
			fw.close();
			bufferedReader.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * args[0] : paths of the file containing ordered contigs names
	 * args[1] : path of the contigs file
	 * args[2] : path of the rearrangend contigs file
	 * @param args
	 */
	public ArrayList<String> reArrangeContigs2(String[] args)
	{
		ArrayList<String> resultList = new ArrayList<String>();
		try
		{
			
			ArrayList<String> list = new ArrayList<String>();
			BufferedReader bufferedReader = new BufferedReader(new FileReader(args[0]));
			String readLine = bufferedReader.readLine();
			while(readLine != null)
			{
				if (!readLine.startsWith(">"))
				{
					String[] params = readLine.split("\t");
					list.add(params[7].trim());
				}
				readLine = bufferedReader.readLine();
			} 
			bufferedReader.close();
			PrintWriter pw = new PrintWriter(new FileWriter(args[2]));
			
			bufferedReader = new BufferedReader(new FileReader(args[1]));
			readLine = bufferedReader.readLine();
			while(readLine != null)
			{
				if (readLine.startsWith(">"))
				{
					boolean flag = false;
					for (String contig : list)
					{
						if (readLine.contains(contig))
						{
							flag = true;
							break;
						}
					}
					if (!flag)
					{
//						System.out.println(readLine);
						pw.println(readLine.split(" ")[0].substring(1));
						if (!resultList.contains(readLine.split(" ")[0].substring(1)))
						{
							resultList.add(readLine.split(" ")[0].substring(1).trim());
						}
					}
				}
				readLine = bufferedReader.readLine();
			}
			System.out.println("Total contigs left " + resultList.size());
			bufferedReader.close();
			pw.flush();
			pw.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return resultList;
	}
	
	public int countScaffolds(String fileName) throws IOException
	{
		int result = 0;
		BufferedReader bufferedReader = new BufferedReader(new FileReader(fileName));
		String readLine = bufferedReader.readLine();
		while(readLine != null)
		{
			if (readLine.startsWith(">"))
			{
				result++;
			}
			readLine = bufferedReader.readLine();
		}
		return result;
	}
	
	public void fetchSequenceFromGbkFile(String inputFile, 
			String outputFile, String seqName,
			boolean withNumbers) throws IOException
	{
		ParseGBKFileParser fileParser = new ParseGBKFileParser();
		PrintWriter printWriter = new PrintWriter(new FileWriter(outputFile));
		
		class Listener extends ParseListener
		{
			PrintWriter pw = null;
			String seqName = null;
			boolean withNumbers = false;
			public Listener(PrintWriter pw , String seqName, boolean withNumbers)
			{
				this.pw = pw;
				this.seqName = seqName;
				this.withNumbers = withNumbers;
			}
			@Override
			public void handleEvent(ParseEvents event) 
			{
				switch((ParseEvents.EventTypes)(event.getEventType()))
				{
				case docStarted:
					break;
				case sequenceStart:
					pw.println(">" + seqName);
					break;
				case sequence:
					String seq = (String)event.getSource();
					String[] params = seq.split(" ");
					StringBuffer buffer = new StringBuffer();
					System.out.println(params[0]);
					for(int i = 1; i < params.length; i++)
					 {
						buffer.append(params[i]);
					 }
					pw.println(buffer.toString());
					break;
				case docEnded:	
					pw.flush();
					pw.close();
				}
			}
		}
		fileParser.addListener(new Listener(printWriter,seqName,withNumbers));
		fileParser.parse(new File(inputFile));
	}
	
	public static void fetchReferenceSeq(String gbkFile, String refSeqFile) throws Exception
	{
		PrepareAllFeaturesFiles allFeaturesFiles = new PrepareAllFeaturesFiles();
		allFeaturesFiles.setReadReference(true).setReferenceSeqFile(refSeqFile)
		.setGbkFile(gbkFile);
		allFeaturesFiles.run();
	}
}
